package com.sj.proxy;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

public class Proxy {

    /**
     * 用来产生新的代理类
     *
     * @param interfce 产生哪个接口的动态代理
     * @param handler  要实现什么样的代理，对接口中的方法前后进行什么样的处理，记录时间or...
     * @return
     * @throws Exception
     */
    public static Object newProxyInstance(Class interfce, InvocationHandler handler) throws Exception {
        String rt = "\r\n";
        String methodStr = "";

        Method[] methods = interfce.getMethods();
        for (Method m : methods) {
            methodStr +=
                    "    public void " + m.getName() + "() {" + rt +
                            "        try {" + rt +
                            "            Method md = " + interfce.getName() + ".class.getMethod(\"" + m.getName() + "\");" + rt +
                            "            h.invoke(this, md);" + rt +
                            "        } catch (Exception e) {" + rt +
                            "            e.printStackTrace();" + rt +
                            "        }" + rt +
                            "    }" + rt;
        }

        String src = "package com.sj.proxy;" + rt +
                "import java.lang.reflect.Method;" + rt +
                "public class TankTimeProxy implements " + interfce.getName() + " {" + rt +
                "    public TankTimeProxy(InvocationHandler h) {" + rt +
                "        this.h = h;" + rt +
                "    }" + rt +
                "    com.sj.proxy.InvocationHandler h;" + rt +

                methodStr +
                "}";

        //先把源代码写到下面
//        String fileUrl = System.getProperty("user.dir") + "/DynamicProxy/src/main/java";
        String fileUrl = System.getProperty("user.dir") + "/DynamicProxy/src/main/java/com/sj/proxy";
        String fileName = fileUrl + "/TankTimeProxy.java";
        File f = new File(fileName);
        FileWriter fw = new FileWriter(f);
        fw.write(src);
        fw.flush();
        fw.close();

        //在程序中编译这段代码
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
        Iterable<? extends JavaFileObject> units = fileMgr.getJavaFileObjects(fileName);
        JavaCompiler.CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);
        t.call();
        fileMgr.close();

        //生成了这个TankTimeProxy.class之后，将其load到内存，并且生成一个对象
        URL[] urls = new URL[]{new URL("file:/" + fileUrl)};
        URLClassLoader urlClassLoader = new URLClassLoader(urls);
        Class clazz = urlClassLoader.loadClass("com.sj.proxy.TankTimeProxy");
        Constructor constructor = clazz.getConstructor(com.sj.proxy.InvocationHandler.class);
        Object object = constructor.newInstance(handler);

        urlClassLoader.close();

        return object;
    }
}
